home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / winterp-1.13 / src-server / xlisp / xlstruct.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-04  |  12.6 KB  |  474 lines

  1. /* -*-C-*-
  2. ********************************************************************************
  3. *
  4. * File:         xlstruct.c
  5. * RCS:          $Header: xlstruct.c,v 1.4 91/03/24 22:25:29 mayer Exp $
  6. * Description:  the defstruct facility
  7. * Author:       David Michael Betz
  8. * Created:      
  9. * Modified:     Fri Oct  4 04:11:37 1991 (Niels Mayer) mayer@hplnpm
  10. * Language:     C
  11. * Package:      N/A
  12. * Status:       X11r5 contrib tape release
  13. *
  14. * WINTERP Copyright 1989, 1990, 1991 Hewlett-Packard Company (by Niels Mayer).
  15. * XLISP version 2.1, Copyright (c) 1989, by David Betz.
  16. *
  17. * Permission to use, copy, modify, distribute, and sell this software and its
  18. * documentation for any purpose is hereby granted without fee, provided that
  19. * the above copyright notice appear in all copies and that both that
  20. * copyright notice and this permission notice appear in supporting
  21. * documentation, and that the name of Hewlett-Packard and David Betz not be
  22. * used in advertising or publicity pertaining to distribution of the software
  23. * without specific, written prior permission.  Hewlett-Packard and David Betz
  24. * make no representations about the suitability of this software for any
  25. * purpose. It is provided "as is" without express or implied warranty.
  26. *
  27. * HEWLETT-PACKARD AND DAVID BETZ DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  28. * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  29. * IN NO EVENT SHALL HEWLETT-PACKARD NOR DAVID BETZ BE LIABLE FOR ANY SPECIAL,
  30. * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  31. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  32. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  33. * PERFORMANCE OF THIS SOFTWARE.
  34. *
  35. * See ./winterp/COPYRIGHT for information on contacting the authors.
  36. * Please send modifications, improvements and bugfixes to mayer@hplabs.hp.com
  37. * Post XLISP-specific questions/information to the newsgroup comp.lang.lisp.x
  38. *
  39. ********************************************************************************
  40. */
  41. static char rcs_identity[] = "@(#)$Header: xlstruct.c,v 1.4 91/03/24 22:25:29 mayer Exp $";
  42.  
  43.  
  44. #include "xlisp.h"
  45.  
  46. /* external variables */
  47. extern LVAL xlenv,xlfenv;
  48. extern LVAL s_lambda,s_quote,lk_key,true;
  49. extern char buf[];
  50.  
  51. /* local variables */
  52. static prefix[STRMAX+1];
  53.  
  54. /* xmkstruct - the '%make-struct' function */
  55. LVAL xmkstruct()
  56. {
  57.     LVAL type,val;
  58.     int i;
  59.  
  60.     /* get the structure type */
  61.     type = xlgasymbol();
  62.  
  63.     /* make the structure */
  64.     val = newstruct(type,xlargc);
  65.  
  66.     /* store each argument */
  67.     for (i = 1; moreargs(); ++i)
  68.     setelement(val,i,nextarg());
  69.     xllastarg();
  70.  
  71.     /* return the structure */
  72.     return (val);
  73. }
  74.  
  75. /* xcpystruct - the '%copy-struct' function */
  76. LVAL xcpystruct()
  77. {
  78.     LVAL str,val;
  79.     int size,i;
  80.     str = xlgastruct();
  81.     xllastarg();
  82.     size = getsize(str);
  83.     val = newstruct(getelement(str,0),size-1);
  84.     for (i = 1; i < size; ++i)
  85.     setelement(val,i,getelement(str,i));
  86.     return (val);
  87. }
  88.  
  89. /* xstrref - the '%struct-ref' function */
  90. LVAL xstrref()
  91. {
  92.     LVAL str,val;
  93.     int i;
  94.     str = xlgastruct();
  95.     val = xlgafixnum(); i = (int)getfixnum(val);
  96.     xllastarg();
  97.     return (getelement(str,i));
  98. }
  99.  
  100. /* xstrset - the '%struct-set' function */
  101. LVAL xstrset()
  102. {
  103.     LVAL str,val;
  104.     int i;
  105.     str = xlgastruct();
  106.     val = xlgafixnum(); i = (int)getfixnum(val);
  107.     val = xlgetarg();
  108.     xllastarg();
  109.     setelement(str,i,val);
  110.     return (val);
  111. }
  112.  
  113. /* xstrtypep - the '%struct-type-p' function */
  114. LVAL xstrtypep()
  115. {
  116.     LVAL type,val;
  117.     type = xlgasymbol();
  118.     val = xlgetarg();
  119.     xllastarg();
  120.     return (structp(val) && getelement(val,0) == type ? true : NIL);
  121. }
  122.  
  123. /* xdefstruct - the 'defstruct' special form */
  124. LVAL xdefstruct()
  125. {
  126.     LVAL structname,slotname,defexpr,sym,tmp,args,body;
  127.     LVAL options,oargs,slots;
  128.     char *pname;
  129.     int slotn;
  130.     
  131.     /* protect some pointers */
  132.     xlstkcheck(6);
  133.     xlsave(structname);
  134.     xlsave(slotname);
  135.     xlsave(defexpr);
  136.     xlsave(args);
  137.     xlsave(body);
  138.     xlsave(tmp);
  139.     
  140.     /* initialize */
  141.     args = body = NIL;
  142.     slotn = 0;
  143.  
  144.     /* get the structure name */
  145.     tmp = xlgetarg();
  146.     if (symbolp(tmp)) {
  147.     structname = tmp;
  148.     strcpy(prefix,getstring(getpname(structname)));
  149.     strcat(prefix,"-");
  150.     }
  151.  
  152.     /* get the structure name and options */
  153.     else if (consp(tmp) && symbolp(car(tmp))) {
  154.     structname = car(tmp);
  155.     strcpy(prefix,getstring(getpname(structname)));
  156.     strcat(prefix,"-");
  157.  
  158.     /* handle the list of options */
  159.     for (options = cdr(tmp); consp(options); options = cdr(options)) {
  160.  
  161.         /* get the next argument */
  162.         tmp = car(options);
  163.         
  164.         /* handle options that don't take arguments */
  165.         if (symbolp(tmp)) {
  166.         pname = (char *) getstring(getpname(tmp));
  167.         xlerror("unknown option",tmp);
  168.         }
  169.  
  170.         /* handle options that take arguments */
  171.         else if (consp(tmp) && symbolp(car(tmp))) {
  172.         pname = (char *) getstring(getpname(car(tmp)));
  173.         oargs = cdr(tmp);
  174.  
  175.         /* check for the :CONC-NAME keyword */
  176.         if (strcmp(pname,":CONC-NAME") == 0) {
  177.  
  178.             /* get the name of the structure to include */
  179.             if (!consp(oargs) || !symbolp(car(oargs)))
  180.             xlerror("expecting a symbol",oargs);
  181.  
  182.             /* save the prefix */
  183.             strcpy(prefix,getstring(getpname(car(oargs))));
  184.         }
  185.  
  186.         /* check for the :INCLUDE keyword */
  187.         else if (strcmp(pname,":INCLUDE") == 0) {
  188.  
  189.             /* get the name of the structure to include */
  190.             if (!consp(oargs) || !symbolp(car(oargs)))
  191.             xlerror("expecting a structure name",oargs);
  192.             tmp = car(oargs);
  193.             oargs = cdr(oargs);
  194.  
  195.             /* add each slot from the included structure */
  196.             slots = xlgetprop(tmp,xlenter("*STRUCT-SLOTS*"));
  197.             for (; consp(slots); slots = cdr(slots)) {
  198.             if (consp(car(slots)) && consp(cdr(car(slots)))) {
  199.  
  200.                 /* get the next slot description */
  201.                 tmp = car(slots);
  202.  
  203.                 /* create the slot access functions */
  204.                 addslot(car(tmp),car(cdr(tmp)),++slotn,&args,&body);
  205.             }
  206.             }
  207.  
  208.             /* handle slot initialization overrides */
  209.             for (; consp(oargs); oargs = cdr(oargs)) {
  210.             tmp = car(oargs);
  211.             if (symbolp(tmp)) {
  212.                 slotname = tmp;
  213.                 defexpr = NIL;
  214.             }
  215.             else if (consp(tmp) && symbolp(car(tmp))) {
  216.                 slotname = car(tmp);
  217.                 defexpr = (consp(cdr(tmp)) ? car(cdr(tmp)) : NIL);
  218.             }
  219.             else
  220.                 xlerror("bad slot description",tmp);
  221.             updateslot(args,slotname,defexpr);
  222.             }
  223.         }
  224.         else
  225.             xlerror("unknown option",tmp);
  226.         }
  227.         else
  228.         xlerror("bad option syntax",tmp);
  229.     }
  230.     }
  231.  
  232.     /* get each of the structure members */
  233.     while (moreargs()) {
  234.     
  235.     /* get the slot name and default value expression */
  236.     tmp = xlgetarg();
  237.     if (symbolp(tmp)) {
  238.         slotname = tmp;
  239.         defexpr = NIL;
  240.     }
  241.     else if (consp(tmp) && symbolp(car(tmp))) {
  242.         slotname = car(tmp);
  243.         defexpr = (consp(cdr(tmp)) ? car(cdr(tmp)) : NIL);
  244.     }
  245.     else
  246.         xlerror("bad slot description",tmp);
  247.     
  248.     /* create a closure for non-trival default expressions */
  249.     if (defexpr != NIL) {
  250.         tmp = newclosure(NIL,s_lambda,xlenv,xlfenv);
  251.         setbody(tmp,cons(defexpr,NIL));
  252.         tmp = cons(tmp,NIL);
  253.         defexpr = tmp;
  254.     }
  255.  
  256.     /* create the slot access functions */
  257.     addslot(slotname,defexpr,++slotn,&args,&body);
  258.     }
  259.     
  260.     /* store the slotnames and default expressions */
  261.     xlputprop(structname,args,xlenter("*STRUCT-SLOTS*"));
  262.  
  263.     /* enter the MAKE-xxx symbol */
  264.     sprintf(buf,"MAKE-%s",getstring(getpname(structname)));
  265.     sym = xlenter(buf);
  266.  
  267.     /* make the MAKE-xxx function */
  268.     args = cons(lk_key,args);
  269.     tmp = cons(structname,NIL);
  270.     tmp = cons(s_quote,tmp);
  271.     body = cons(tmp,body);
  272.     body = cons(xlenter("%MAKE-STRUCT"),body);
  273.     body = cons(body,NIL);
  274.     setfunction(sym,
  275.         xlclose(sym,s_lambda,args,body,xlenv,xlfenv));
  276.  
  277.     /* enter the xxx-P symbol */
  278.     sprintf(buf,"%s-P",getstring(getpname(structname)));
  279.     sym = xlenter(buf);
  280.  
  281.     /* make the xxx-P function */
  282.     args = cons(xlenter("X"),NIL);
  283.     body = cons(xlenter("X"),NIL);
  284.     tmp = cons(structname,NIL);
  285.     tmp = cons(s_quote,tmp);
  286.     body = cons(tmp,body);
  287.     body = cons(xlenter("%STRUCT-TYPE-P"),body);
  288.     body = cons(body,NIL);
  289.     setfunction(sym,
  290.         xlclose(sym,s_lambda,args,body,NIL,NIL));
  291.  
  292.     /* enter the COPY-xxx symbol */
  293.     sprintf(buf,"COPY-%s",getstring(getpname(structname)));
  294.     sym = xlenter(buf);
  295.  
  296.     /* make the COPY-xxx function */
  297.     args = cons(xlenter("X"),NIL);
  298.     body = cons(xlenter("X"),NIL);
  299.     body = cons(xlenter("%COPY-STRUCT"),body);
  300.     body = cons(body,NIL);
  301.     setfunction(sym,
  302.         xlclose(sym,s_lambda,args,body,NIL,NIL));
  303.  
  304.     /* restore the stack */
  305.     xlpopn(6);
  306.  
  307.     /* return the structure name */
  308.     return (structname);
  309. }
  310.  
  311. /* xlrdstruct - convert a list to a structure (used by the reader) */
  312. LVAL xlrdstruct(list)
  313.   LVAL list;
  314. {
  315.     LVAL structname,sym,slotname,expr,last,val;
  316.  
  317.     /* protect the new structure */
  318.     xlsave1(expr);
  319.  
  320.     /* get the structure name */
  321.     if (!consp(list) || !symbolp(car(list)))
  322.     xlerror("bad structure initialization list",list);
  323.     structname = car(list);
  324.     list = cdr(list);
  325.  
  326.     /* enter the MAKE-xxx symbol */
  327.     sprintf(buf,"MAKE-%s",getstring(getpname(structname)));
  328.  
  329.     /* initialize the MAKE-xxx function call expression */
  330.     expr = cons(xlenter(buf),NIL);
  331.     last = expr;
  332.  
  333.     /* turn the rest of the initialization list into keyword arguments */
  334.     while (consp(list) && consp(cdr(list))) {
  335.  
  336.     /* get the slot keyword name */
  337.     slotname = car(list);
  338.     if (!symbolp(slotname))
  339.         xlerror("expecting a slot name",slotname);
  340.     sprintf(buf,":%s",getstring(getpname(slotname)));
  341.  
  342.     /* add the slot keyword */
  343.     rplacd(last,cons(xlenter(buf),NIL));
  344.     last = cdr(last);
  345.     list = cdr(list);
  346.  
  347.     /* add the value expression */
  348.     rplacd(last,cons(car(list),NIL));
  349.     last = cdr(last);
  350.     list = cdr(list);
  351.     }
  352.  
  353.     /* make sure all of the initializers were used */
  354.     if (consp(list))
  355.     xlerror("bad structure initialization list",list);
  356.  
  357.     /* invoke the creation function */
  358.     val = xleval(expr);
  359.  
  360.     /* restore the stack */
  361.     xlpop();
  362.  
  363.     /* return the new structure */
  364.     return (val);
  365. }
  366.  
  367. /* xlprstruct - print a structure (used by printer) */
  368. xlprstruct(fptr,vptr,flag)
  369.   LVAL fptr,vptr; int flag;
  370. {
  371.     LVAL next;
  372.     int i,n;
  373.     xlputc(fptr,'#'); xlputc(fptr,'S'); xlputc(fptr,'(');
  374.     xlprint(fptr,getelement(vptr,0),flag);
  375.     next = xlgetprop(getelement(vptr,0),xlenter("*STRUCT-SLOTS*"));
  376.     for (i = 1, n = getsize(vptr) - 1; i <= n && consp(next); ++i) {
  377.     if (consp(car(next))) { /* should always succeed */
  378.         xlputc(fptr,' ');
  379.         xlprint(fptr,car(car(next)),flag);
  380.         xlputc(fptr,' ');
  381.         xlprint(fptr,getelement(vptr,i),flag);
  382.     }
  383.     next = cdr(next);
  384.     }
  385.     xlputc(fptr,')');
  386. }
  387.  
  388. /* addslot - make the slot access functions */
  389. LOCAL addslot(slotname,defexpr,slotn,pargs,pbody)
  390.   LVAL slotname,defexpr; int slotn; LVAL *pargs,*pbody;
  391. {
  392.     LVAL sym,args,body,tmp;
  393.     
  394.     /* protect some pointers */
  395.     xlstkcheck(4);
  396.     xlsave(sym);
  397.     xlsave(args);
  398.     xlsave(body);
  399.     xlsave(tmp);
  400.     
  401.     /* construct the update function name */
  402.     sprintf(buf,"%s%s",prefix,getstring(getpname(slotname)));
  403.     sym = xlenter(buf);
  404.     
  405.     /* make the access function */
  406.     args = cons(xlenter("S"),NIL);
  407.     body = cons(cvfixnum((FIXTYPE)slotn),NIL);
  408.     body = cons(xlenter("S"),body);
  409.     body = cons(xlenter("%STRUCT-REF"),body);
  410.     body = cons(body,NIL);
  411.     setfunction(sym,
  412.         xlclose(sym,s_lambda,args,body,NIL,NIL));
  413.  
  414.     /* make the update function */
  415.     args = cons(xlenter("V"),NIL);
  416.     args = cons(xlenter("S"),args);
  417.     body = cons(xlenter("V"),NIL);
  418.     body = cons(cvfixnum((FIXTYPE)slotn),body);
  419.     body = cons(xlenter("S"),body);
  420.     body = cons(xlenter("%STRUCT-SET"),body);
  421.     body = cons(body,NIL);
  422.     xlputprop(sym,
  423.           xlclose(NIL,s_lambda,args,body,NIL,NIL),
  424.           xlenter("*SETF*"));
  425.  
  426.     /* add the slotname to the make-xxx keyword list */
  427.     tmp = cons(defexpr,NIL);
  428.     tmp = cons(slotname,tmp);
  429.     tmp = cons(tmp,NIL);
  430.     if ((args = *pargs) == NIL)
  431.     *pargs = tmp;
  432.     else {
  433.     while (cdr(args) != NIL)
  434.         args = cdr(args);
  435.     rplacd(args,tmp);
  436.     }
  437.     
  438.     /* add the slotname to the %make-xxx argument list */
  439.     tmp = cons(slotname,NIL);
  440.     if ((body = *pbody) == NIL)
  441.     *pbody = tmp;
  442.     else {
  443.     while (cdr(body) != NIL)
  444.         body = cdr(body);
  445.     rplacd(body,tmp);
  446.     }
  447.  
  448.     /* restore the stack */
  449.     xlpopn(4);
  450. }
  451.  
  452. /* updateslot - update a slot definition */
  453. LOCAL updateslot(args,slotname,defexpr)
  454.   LVAL args,slotname,defexpr;
  455. {
  456.     LVAL tmp;
  457.     for (; consp(args); args = cdr(args))
  458.     if (slotname == car(car(args))) {
  459.         if (defexpr != NIL) {
  460.         xlsave1(tmp);
  461.         tmp = newclosure(NIL,s_lambda,xlenv,xlfenv);
  462.         setbody(tmp,cons(defexpr,NIL));
  463.         tmp = cons(tmp,NIL);
  464.         defexpr = tmp;
  465.         xlpop();
  466.         }
  467.         rplaca(cdr(car(args)),defexpr);
  468.         break;
  469.     }
  470.     if (args == NIL)
  471.     xlerror("unknown slot name",slotname);
  472. }
  473.